﻿using System;
using System.Diagnostics;
using JetBrains.Annotations;
using MugenMvvmToolkit.Infrastructure;
using MugenMvvmToolkit.Interfaces.Views;
#if NET45
using System.Runtime.CompilerServices;
#endif

namespace MugenMvvmToolkit.Utils
{
    internal static class Thrower
    {
        #region Methods

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void ViewModelIsNotInitialized(Type vmType)
        {
            throw new InvalidOperationException(string.Format("The view-model {0} is not initialized.", vmType));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void ViewNotFound(Type viewModelType, Type viewType = null)
        {
            if (viewType == null)
                viewType = typeof(IView);
            throw new InvalidOperationException(
                string.Format(@"Unable to find a suitable view '{1}' for the view model '{0}'. 
Make sure that you add an attribute ViewModelAttribute or PageViewModelAttribute over the desired View or registered it manually.", viewModelType,
                    viewType));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void ViewModelNotFound(string viewName)
        {
            throw new InvalidOperationException(
                string.Format(@"Unable to find a suitable view model for the view with name '{0}'. 
Make sure that you add an attribute ViewModelAttribute or PageViewModelAttribute over the desired View or registered it manually.", viewName));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void ResourceNotFound(string resourceName, Type resourceType)
        {
            throw new InvalidOperationException(
                string.Format("Resource with the name '{0}' is not found in the '{1}' type.", resourceName,
                    resourceType));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void ResourceIsNotString(string resourceName, Type resourceType)
        {
            throw new InvalidOperationException(
                string.Format("Resource with the name '{0}' in the '{1}' type, is not a string.", resourceName,
                    resourceType));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void ResourceHasNotGetter(string resourceName, Type resourceType)
        {
            throw new InvalidOperationException(
                string.Format("Resource with the name '{0}' in the '{1}' type, is not have a get method.",
                    resourceName, resourceType));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void DuplicateViewMapping(Type viewType, Type viewModelType, string name)
        {
            throw new InvalidOperationException(
                string.Format(
                    "The view model mapping already exist for view with the '{0}' type to the view model with type {1} with name {2}",
                    viewType, viewModelType, name));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void DuplicateViewModelMapping(Type viewType)
        {
            throw new InvalidOperationException(
                string.Format("The view model for view with the {0} type, registreted more that once.",
                    viewType));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void LockTimeout(string message)
        {
            throw new LockTimeoutException(message);
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void IntNonNegativeOutOfRange()
        {
            // ReSharper disable once NotResolvedInText
            throw new ArgumentOutOfRangeException("value",
                "Number must be either non-negative and less than or equal to Int32.MaxValue or -1.");
        }

#if !TASKSUPPORT
#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void OperationResultIsNotEmpty()
        {
            throw new InvalidOperationException(
                "An attempt was made to transition a operation to a final state when it had already completed.");
        }
#endif

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void ViewModelWasInitialized()
        {
            throw new InvalidOperationException("The view model is already initialized.");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void ObjectFrozen(string className)
        {
            throw new InvalidOperationException(
                string.Format("The '{0}' cannot be changed. You need to create a new instance of the '{0}'.", className));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void SupportedOnlyInDesignMode()
        {
            throw new NotSupportedException("Not supported not in design mode.");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void DesignBootstrapperNotFound()
        {
            throw new InvalidOperationException(
                @"To enable a DesignBootstrapper create a file App.xaml and set value for build action as ApplicationDefinition. 
After this, add your instance of DesignBootstrapper with key = 'DesignBootstrapper'.
Example: <wpfApplication:MyDesignBootstrapper x:Key=""DesignBootstrapper""/>");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void ParameterTypeMismatch([InvokerParameterName]string paramName, string parameterTypeName)
        {
            throw new ArgumentNullException(paramName, string.Format("Parameter can only be a {0}.", parameterTypeName));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void DuplicateInterface(string itemName, string interfaceName, Type type)
        {
            throw new InvalidOperationException(
                string.Format(
                    "The {0} can implement an interface {1} only once. The {0} with type {2}, implement it more that once.",
                    itemName, interfaceName, type));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void EnumOutOfRange(string paramName, Enum @enum)
        {
            throw new ArgumentOutOfRangeException(paramName, string.Format("Unhandled enum - {0}", @enum));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void CommandCannotBeExecuted()
        {
            throw new InvalidOperationException(
                "The method Execute in RelayCommand cannot be executed because the CanExecute method returns a false value.");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void CreateViewModelInvalidMethod()
        {
            throw new ArgumentException("To create view-model use this methods: GetViewModel<T> or GetViewModel.");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void DialogIsOpened()
        {
            throw new InvalidOperationException(
                   "The dialog is open. Before you create a new dialog you should to close the previous one.");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void DialogIsClosed()
        {
            throw new InvalidOperationException(
                    "The dialog is closed. Before you close the dialog you should show it.");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void NotConvertableState(Enum from, Enum to)
        {
            throw new InvalidOperationException(string.Format("The {0} state cannot be converted to the {1} state.", from, to));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void CancelChangesObjectNotFound()
        {
            throw new InvalidOperationException("Before call the Cancel method you should call the Save method.");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void IntOutOfRangeCollection(string paramName)
        {
            throw new ArgumentOutOfRangeException(paramName, "Index must be within the bounds of the List.");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void CapacityLessThanCollection(string paramName)
        {
            throw new ArgumentOutOfRangeException(paramName, "The Capacity should be greater or equal than collection.");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void DuplicateItemCollection()
        {
            throw new ArgumentException("The item already in the collection.");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void ValidatorIsNotInitialized(string paramName)
        {
            throw new ArgumentException("The validator is not initialized.", paramName);
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void ValidatorWasInitialized()
        {
            throw new ArgumentException("The validator already has a contex, use the Clone method to create a new validator.");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void ValidatorInvalidContex()
        {
            throw new ArgumentException("The specified context cannot be used in the current validator.");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void DuplicateValidator(Type validatorType)
        {
            throw new ArgumentException(
                        string.Format(
                            "The validator with type {0} already registered, because validator is unique you can add only one instance of it.",
                            validatorType));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void EditorIsNotInitialized()
        {
            throw new InvalidOperationException(
                    "The editor is't initialized. To initialize editor call the InitializeEntity method.");
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void CyclicValidation(string propertyName)
        {
            throw new InvalidOperationException(
                    string.Format(@"A cyclical validation was detected. Property name = ""{0}"".
Make sure you do not call the validation method during validation process.
To disable the detection of cyclical validation set this property to false. (this.CyclicValidationDetectionEnabled = false or GlobalSettings.CyclicValidationDetectionEnabled = false).",
                        propertyName ?? string.Empty));
        }

#if NET45
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        [DebuggerStepThrough]
        internal static void MissingMetadataProperty(Type type, string propertyName, Type classType)
        {
            throw new MissingMemberException(
                string.Format(
                    "The type '{0}' does not contain property with name {1}, declareted in MetadataType '{2}'", type,
                    propertyName, classType.FullName));
        }

        #endregion
    }
}